_require local "../../../../basis.smi"
_require local "../../../libs/util/main/TermFormat.smi"
_require local "../../../extensions/format-utils/main/SmlppgUtil.ppg.smi"

_require "../../../data/symbols/main/Symbol.smi"
_require "../../../data/symbols/main/Loc.smi"
_require "../../../libs/ids/main/LocalID.smi"
_require "../../../../smlformat-lib.smi"
_require "./RequirePath.smi"
_require "./Absyn.smi"
_require local "./AbsynFormatter.smi"
_require "./AbsynTy.smi"
_require local "./AbsynTyFormatter.smi"
_require "./InterfaceName.ppg.smi"

structure AbsynInterface =
struct
  datatype constraint =
      SIG_TRANSPARENT
    | SIG_OPAQUE

  type ty = Absyn.ty
  type symbol = Symbol.symbol
  type longsymbol = Symbol.longsymbol
  type loc = Loc.loc
  datatype overloadInstance =
      INST_OVERLOAD of {tyvar: Absyn.tvar,
                        expTy: ty,
                        matches: {instTy: ty, instance: overloadInstance} list,
                        loc: loc}
    | INST_LONGVID of {longsymbol: longsymbol}

  type overloadCase =
      {tyvar: Absyn.tvar,
       expTy: ty,
       matches: {instTy: ty, instance: overloadInstance} list,
       loc: loc}

  datatype valbindBody =
      VAL_EXTERN of {ty: ty}
    | VALALIAS_EXTERN of longsymbol
    | VAL_BUILTIN of {builtinSymbol: symbol, ty: ty}
    | VAL_OVERLOAD of overloadCase

  type valbind =
      {symbol: symbol, body: valbindBody, loc: loc}

  type typbind_trans
    = {tyvars: Absyn.tvar list, symbol: symbol, ty: ty, loc: loc}

  datatype opaque_impl = datatype AbsynTy.opaque_impl

  datatype typbind =
      TRANSPARENT of typbind_trans
    | OPAQUE of {eq: bool, tyvars: Absyn.tvar list, symbol: symbol,
                 runtimeTy: opaque_impl, loc: loc}

  type conbind =
      {symbol: symbol, ty: ty option, loc:loc}

  type datbind =
      {tyvars: Absyn.tvar list, symbol: symbol, conbind: conbind list, loc:loc}

  datatype exbind =
      EXNDEF of {symbol: symbol, ty: ty option, loc: loc}
    | EXNREP of {symbol: symbol, longsymbol: longsymbol, loc: loc}

  datatype idec =
      IVAL of valbind
    | ITYPE of typbind list
    | IDATATYPE of {datbind: datbind list, withType: typbind_trans list,
                    loc: loc}
    | ITYPEREP of {symbol: symbol, longsymbol: longsymbol, loc: loc}
    | ITYPEBUILTIN of {symbol: symbol, builtinSymbol: symbol,loc: loc}
    | IEXCEPTION of exbind list
    | ISTRUCTURE of {symbol: symbol, strexp: istrexp, loc: loc}


  and istrexp =
      ISTRUCT of {decs: idec list, loc: loc}
    | ISTRUCTREP of {longsymbol:longsymbol, loc: loc}
    | IFUNCTORAPP of {functorSymbol:symbol, argument:longsymbol, loc: loc}

  type strbind =
      {
        symbol: symbol,
        strexp: istrexp,
        loc: loc
      }

  type sigbind =
      {symbol: symbol, sigexp: Absyn.sigexp, loc: loc}

  datatype funParam =
      FUNPARAM_FULL of {symbol: symbol, sigexp: Absyn.sigexp}
    | FUNPARAM_SPEC of Absyn.spec

  type funbind =
      {
        functorSymbol: symbol,
        param: funParam,
        strexp: istrexp,
        loc: loc
      }

  datatype fixity =
      INFIXL of string option
    | INFIXR of string option
    | NONFIX

  datatype itopdec =
      IDEC of idec
    | IFUNDEC of funbind
    | IINFIX of {fixity: fixity, symbols: symbol list, loc: loc}

  datatype irequire =
      REQUIRE of RequirePath.path * Symbol.symbol list * loc
    | LOCAL_REQUIRE of RequirePath.path * Symbol.symbol list * loc
    | LOCAL_USE of RequirePath.path * loc

  datatype itop =
      INTERFACE of
      {
        requires: irequire list,
        provide: itopdec list
      }
    | INCLUDES of
      {
        includes: (RequirePath.path * loc) list,
        topdecs: Absyn.topdec list
      }

  type interface_dec =
      {
        interfaceId : InterfaceID.id,
        interfaceName : InterfaceName.interface_name,
        requiredIds : {id : InterfaceID.id, loc : loc} list,
        provideTopdecs : itopdec list
      }

  type interface =
      {
        interfaceDecs : interface_dec list,
        provide :
          {requiredIds : {id : InterfaceID.id, loc : loc} list,
           locallyRequiredIds : {id : InterfaceID.id, loc : loc} list,
           provideTopdecs : itopdec list,
           topdecsInclude: Absyn.topdec list}
      }

  type compile_unit =
      {
        interface : interface option,
        topdecsSource : Absyn.topdec list
      }

  type interface_unit =
      {
        interfaceDecs : interface_dec list,
        requiredIds : {id: InterfaceID.id, loc: loc} list,
        topdecsInclude : Absyn.topdec list
      }

  val format_constraint
      : constraint -> SMLFormat.FormatExpression.expression list
  val format_ty : ty -> SMLFormat.FormatExpression.expression list
  val format_loc : loc -> SMLFormat.FormatExpression.expression list
  val format_overloadInstance
      : overloadInstance -> SMLFormat.FormatExpression.expression list
(*
  val format_overloadMatch
      : overloadMatch -> SMLFormat.FormatExpression.expression list
*)
  val format_overloadCase
      : overloadCase -> SMLFormat.FormatExpression.expression list
  val format_valbindBody
      : SMLFormat.FormatExpression.expression list
        -> valbindBody -> SMLFormat.FormatExpression.expression list
  val format_valbind
      : valbind -> SMLFormat.FormatExpression.expression list
  val format_typbind
      : typbind -> SMLFormat.FormatExpression.expression list
  val format_conbind
      : conbind -> SMLFormat.FormatExpression.expression list
  val format_datbind
      : datbind -> SMLFormat.FormatExpression.expression list
  val format_exbind
      : exbind -> SMLFormat.FormatExpression.expression list
  val format_idec
      : idec -> SMLFormat.FormatExpression.expression list
  val format_istrexp
      : istrexp -> SMLFormat.FormatExpression.expression list
  val format_strbind
      : strbind -> SMLFormat.FormatExpression.expression list
  val format_sigbind
      : sigbind -> SMLFormat.FormatExpression.expression list
  val format_funParam
      : funParam -> SMLFormat.FormatExpression.expression list
  val format_funbind
      : funbind -> SMLFormat.FormatExpression.expression list
  val format_fixity
      : fixity -> SMLFormat.FormatExpression.expression list
  val format_itopdec
      : itopdec -> SMLFormat.FormatExpression.expression list
  val format_itop
      : itop -> SMLFormat.FormatExpression.expression list
  val format_interface_dec
      : interface_dec -> SMLFormat.FormatExpression.expression list
  val format_interface
      : interface -> SMLFormat.FormatExpression.expression list
  val format_compile_unit
      : compile_unit -> SMLFormat.FormatExpression.expression list
  val format_interface_unit
      : interface_unit -> SMLFormat.FormatExpression.expression list

end
